package framework.util.queryFilter.vo;


import framework.util._BeanUtil;
import framework.util.queryFilter.service.impl.QueryFilter;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;

/**
 * QueryFilter的过滤对象
 *
 * @author 吴宇亮 on 2019/2/15 0015 15:58
 */
public class Where extends AbstactSql {
    /** 模糊查询字符串, 使用示例：【后端】filter.where("cname", Where.like, "xxx")；【前端】where_cname_like : xxx, 等价于 name like '%xxx%' **/
    public static final String like = "like";
    /** 模糊查询字符串, 使用示例：【后端】filter.where("name", Where.leftLike, "xxx")；【前端】where_cname_leftLike : xxx, 等价于 name like 'xxx%' **/
    public static final String leftLike = "leftLike";
    /** 模糊查询字符串, 使用示例：【后端】filter.where("name", Where.rightLike, "xxx")；【前端】where_cname_rightLike : xxx, 等价于 name like '%xxx' **/
    public static final String rightLike = "rightLike";

    /** 精确查询, 使用示例：【后端】filter.where("plid", Where.eq, -1)；【前端】where_plid_eq : -1, 等价于 plid = -1 **/
    public static final String eq = "eq";
    /** 精确查询, 使用示例：【后端】filter.where("plid", Where.notEq, -1)；【前端】where_plid_notEq : -1, 等价于 plid != -1 **/
    public static final String notEq = "notEq";

    /** 比较查询, 使用示例：【后端】filter.where("amount", Where.lessThan, 10)；【前端】where_amount_lessThan : 10, 等价于 amount < 10 **/
    public static final String lessThan = "lessThan";
    /** 比较查询, 使用示例：【后端】filter.where("amount", Where.lessEq, 10)；【前端】where_amount_lessEq : 10, 等价于 amount <= 10 **/
    public static final String lessEq = "lessEq";
    /** 比较查询, 使用示例：【后端】filter.where("amount", Where.bigThan, 10)；【前端】where_amount_bigThan : 10, 等价于 amount > 10 **/
    public static final String bigThan = "bigThan";
    /** 比较查询, 使用示例：【后端】filter.where("amount", Where.bigEq, 10)；【前端】where_amount_bigEq : 10, 等价于 amount >= 10 **/
    public static final String bigEq = "bigEq";

    /** In过滤, 使用示例：【后端】filter.where("lid", Where.in, "1,2,3")；【前端】where_lid_in : 1,2,3, 等价于 lid in (1,2,3) **/
    public static final String in = "in";
    /** OR过滤, 使用示例：【后端】filter.where("age", Where.orEq, "1,2,3")；【前端】where_age_orEq : 1,2,3, 等价于 age=1 or age=2 or age=3); **/
    public static final String orEq = "orEq";
    /** ORLIKE过滤, 正对于字符串, 使用示例：【后端】filter.where("name", Where.orLike, "张三,李四,王五")；【前端】where_name_orLike : 张三,李四,王五, 等价于 name like '%张三%' or age like '%李四%' or age like '%王五%') **/
    public static final String orLike = "orLike";

    /** isNull过滤, 使用示例：【后端】filter.where("age", Where.isNull, "")；【前端】where_age_isNull : '', 等价于 age is null **/
    public static final String isNull = "isNull";
    /** isNotNull过滤, 使用示例：【后端】filter.where("age", Where.isNotNull, "")；【前端】where_age_isNotNull : '',  等价于 age is not null **/
    public static final String IsNotNull = "isNotNull";

    /** 最值问题：在where过滤的范围里，查出最大的值，并且获取max的其他字段，max有可能多条。由于过于复杂，不进行封装 **/
    @Deprecated
    public static final String MAX = "max";
    /** 最值问题：在where过滤的范围里，查出最大的值，并且获取max的其他字段，max有可能多条。由于过于复杂，不进行封装 **/
    @Deprecated
    public static final String MIN = "min";

    /**
     *
     * @param whereField 要查询的字段名称
     * @param whereType 查询类型,如：like, in, isnull等
     * @param whereValue 查询的值
     * @param paramMap 辅助myBatis拼接 #{} 的sql
     */
    public Where(String whereField, String whereType, Object whereValue, Map<String, Object> paramMap) {
        this.whereField = whereField;
        this.whereType = whereType;
        this.whereValue = whereValue;
        this.paramMap = paramMap;
    }

    /** 要查询的字段名称 **/
    private String whereField;
    /** 查询类型，如Where.like, Where.eq等 **/
    private String whereType;
    /** 查询的值，如果filter.where("name", Where.like, "xxx")，xxx就是要查询的值 **/
    private Object whereValue;
    /** 查询参数map，用于给映射文件通过'#'号注入查询值。<br/>
     *  在IBaseServiceImpl生成完sql，如：lid = #{_q.lid, jdbcType=VARCHAR} <br/>
     *  然后将这个paramMap传递给Mybatis。Mybatis就会从这个paramMap拿到lid真正的值，相当于paramMap.get("lid")
     **/
    private Map<String, Object> paramMap;

    /**
     * sql会对字符串进行隐形转换。因为这个是后台自个调用的，所以不考虑sql注入问题
     */
    public static String generatorSql(String whereField, String whereType, Object whereValue){
        switch (whereType){
            case like:
                return _BeanUtil.transformUpperCase2_(whereField) + " like '%" + whereValue + "%'";
            case leftLike:
                return _BeanUtil.transformUpperCase2_(whereField) + " like '" + whereValue + "%'";
            case rightLike:
                return _BeanUtil.transformUpperCase2_(whereField) + " like '%" + whereValue + "'";
            case eq:
                return _BeanUtil.transformUpperCase2_(whereField) + " = '" + whereValue + "'";
            case notEq:
                return _BeanUtil.transformUpperCase2_(whereField) + " != '" + whereValue + "'";
            case lessThan:
                return _BeanUtil.transformUpperCase2_(whereField) + " < " + whereValue;
            case lessEq:
                return _BeanUtil.transformUpperCase2_(whereField) + " <= " + whereValue;
            case bigThan:
                return _BeanUtil.transformUpperCase2_(whereField) + " > " + whereValue;
            case bigEq:
                return _BeanUtil.transformUpperCase2_(whereField) + " >= " + whereValue;
            case in:
                return _BeanUtil.transformUpperCase2_(whereField) + " in (" + whereValue + ")";
            case isNull:
                return _BeanUtil.transformUpperCase2_(whereField) + " is null";
            case IsNotNull:
                return _BeanUtil.transformUpperCase2_(whereField) + " is not null";
            default:
                return "";
        }
    }

    /**
     * 生成MyBatis的sql
     */
    @Override
    public void generatorSql(Class persistType) throws NoSuchFieldException {
        switch (whereType){
            case like:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " like #{_q." + whereField + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "}";
                paramMap.put(whereField, "%"+whereValue+"%");
                break;
            case leftLike:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " like #{_q." + whereField + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "}";
                paramMap.put(whereField, whereValue+"%");
                break;
            case rightLike:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " like #{_q." + whereField + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "}";
                paramMap.put(whereField, "%"+whereValue);
                break;
            case eq:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " = #{_q." + whereField + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "}";
                paramMap.put(whereField, whereValue);
                break;
            case notEq:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " != #{_q." + whereField + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "}";
                paramMap.put(whereField, whereValue);
                break;
            case lessThan:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " < #{_q." + whereField + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "}";
                paramMap.put(whereField, whereValue);
                break;
            case lessEq:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " <= #{_q." + whereField + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "}";
                paramMap.put(whereField, whereValue);
                break;
            case bigThan:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " > #{_q." + whereField + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "}";
                paramMap.put(whereField, whereValue);
                break;
            case bigEq:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " >= #{_q." + whereField + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "}";
                paramMap.put(whereField, whereValue);
                break;
            case in:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " in ( #{_q." + whereField + ", jdbcType=VARCHAR})";
                paramMap.put(whereField, whereValue);
                break;
            case orEq:
                //WHERE (t.brand = 'samsung' OR t.brand = 'HONOR') AND t.android_version=9
                this.generatorSql = "";
                String[] whereValueArr = whereValue.toString().split(",");
                for (int i = 0; i < whereValueArr.length; i++) {
                    String whereFieldIndex = whereField + i;
                    if(i != whereValueArr.length - 1){
                        this.generatorSql += whereField + " = #{_q." + whereFieldIndex + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "} or ";
                    }else{
                        this.generatorSql += whereField + " = #{_q." + whereFieldIndex + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "} ";
                    }
                    paramMap.put(whereFieldIndex, whereValueArr[i]);
                }
                this.generatorSql = "(" + this.generatorSql + ")";
                break;
            case orLike:
                //WHERE (t.brand LIKE '%samsung%' OR t.brand LIKE '%HONOR%') AND t.android_version=9
                this.generatorSql = "";
                String[] _whereValueArr = whereValue.toString().split(",");
                for (int i = 0; i < _whereValueArr.length; i++) {
                    String whereFieldIndex = whereField + i;
                    if(i != _whereValueArr.length - 1){
                        this.generatorSql += whereField + " like #{_q." + whereFieldIndex + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "} or ";
                    }else{
                        this.generatorSql += whereField + " like #{_q." + whereFieldIndex + ", jdbcType=" + QueryFilter.fieldTypeMap.get( persistType.getDeclaredField(whereField).getType() ) + "} ";
                    }
                    paramMap.put(whereFieldIndex, _whereValueArr[i]);
                }
                this.generatorSql = "(" + this.generatorSql + ")";
                break;
            case isNull:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " is null ";
                break;
            case IsNotNull:
                this.generatorSql = _BeanUtil.transformUpperCase2_(whereField) + " is not null ";
                break;
            default:
                break;
        }
    }

    public String getWhereField() {
        return whereField;
    }

    public void setWhereField(String whereField) {
        this.whereField = whereField;
    }

    public String getWhereType() {
        return whereType;
    }

    public void setWhereType(String whereType) {
        this.whereType = whereType;
    }

    public Object getWhereValue() {
        return whereValue;
    }

    public void setWhereValue(Object whereValue) {
        this.whereValue = whereValue;
    }

    public Map<String, Object> getParamMap() {
        return paramMap;
    }

    public void setParamMap(Map<String, Object> paramMap) {
        this.paramMap = paramMap;
    }

}
